export default class WS {

    constructor(url){
        this.url = url;
        this.events = {};
        this.connectLock = false; // 连接锁，防止多次重复连接
        this.heartInterval = null; // 心跳定时器
        this.heartTime = 50000; // 心跳周期50秒，检查一次
        this.ws = this.initConnect(this.url); // 连接socket服务
    }
    // 连接socket服务
    initConnect(url) {
        let ws = null;
        try{
            console.log('创建 websocket...')
            ws = this.createWebSocket(url);
            ws && this.bindEvents(ws);
        }catch(e){
            console.log('catch 异常的url请求地址...')
            this.reconnect(url)
        }
        return ws;
    }

    //重新连接
    reconnect(url){
        //error和close都会重新连接，
        //第二个过来连接时，锁已经上锁了，避免重复连接
        if(this.connectLock){return}
        this.connectLock = true;
        setTimeout(() => {
            this.initConnect(url);
            this.connectLock = false;
            console.log('连接锁关闭...')
        },2000)
    }

    createWebSocket(url){
        let ws
        if('WebSocket' in window){
            ws = new WebSocket(url);
        }else if('MozWebSocket' in window){
            ws = new MozWebSocket(url);
        }else{
            alert('您的浏览器不支持webSocket')
        }
        return ws;
    }

    //绑定事件socket
    bindEvents(ws){
        // socket连接成功后的回调
        ws.onopen = e => this.connectSuc(e,ws);
        // 接收服务端消息
        ws.onmessage = e => this.message(e,ws);
        // socket关闭
        ws.onclose = e => this.close(e,ws,'close');
        ws.onerror = e => this.close(e,ws,'error');
    }

    // 绑定事件
    $on(event, handler) {
        (this.events[event] || (this.events[event] = [])).push(handler);
    }   

    // 订阅事件
    $emit(event, ...data) {
        if(typeof event != 'string'){return}
        event = this.events[event] || [];
        for (var i = 0; i < event.length; i++) {
            event[i].apply(this, data);
        }
    }

    // socket连接成功的事件
    connectSuc(e,ws) {
        this.stopHeart().heartCheck();
        this.$emit('connectSuc', e, ws, this);
    }

    // socket发送消息的事件
    message(e,ws) {
        this.stopHeart().heartCheck();
        this.$emit('message', e, ws, this);
    }

    // socket断开的事件
    close(e,ws,type) {
        console.log('错误：wesocket '+type+'...')
        this.reconnect(this.url);
        this.$emit(type, e, ws, this);
    }

    // 停止心跳检查
    stopHeart() {
        clearTimeout(this.heartInterval);
        return this;
    }

    // 心跳检查
    heartCheck() {
        this.heartInterval = setTimeout(() => {
            this.reconnect(this.url)
        },this.heartTime)
    }
};
